import { Graph, Node, Path, Edge, Platform, StringExt } from '@antv/x6'


// 加工类型列表 
export const PROCESSING_TYPE_LIST = [
    {
        type: 'FILTER',
        name: '数据筛选',
    },
    {
        type: 'JOIN',
        name: '数据连接',
    },
    {
        type: 'UNION',
        name: '数据合并',
    },
    {
        type: 'AGG',
        name: '数据聚合',
    },

    {
        type: 'OUTPUT',
        name: '数据输出',
    },
]

// 不同节点类型的icon
export const NODE_TYPE_LOGO = {
    INPUT:
        'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*RXnuTpQ22xkAAAAAAAAAAAAADtOHAQ/original', // 数据输入
    FILTER:
        'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*ZJ6qToit8P4AAAAAAAAAAAAADtOHAQ/original', // 数据筛选
    JOIN: 'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*EHqyQoDeBvIAAAAAAAAAAAAADtOHAQ/original', // 数据连接
    UNION:
        'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*k4eyRaXv8gsAAAAAAAAAAAAADtOHAQ/original', // 数据合并
    AGG: 'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*TKG8R6nfYiAAAAAAAAAAAAAADtOHAQ/original', // 数据聚合
    OUTPUT:
        'https://mdn.alipayobjects.com/huamei_f4t1bn/afts/img/A*zUgORbGg1HIAAAAAAAAAAAAADtOHAQ/original', // 数据输出
}

/**
 * 根据起点初始下游节点的位置信息
 * @param node 起始节点
 * @param graph
 * @returns
 */
export const getDownstreamNodePosition = (
    node: Node,
    graph: Graph,
    dx = 250,
    dy = 100,
) => {
    // 找出画布中以该起始节点为起点的相关边的终点id集合
    const downstreamNodeIdList: string[] = []
    graph.getEdges().forEach((edge) => {
        const originEdge = edge.toJSON()?.data
        if (originEdge?.source === node.id) {
            downstreamNodeIdList.push(originEdge.target)
        }
    })
    // 获取起点的位置信息
    const position = node.getPosition()
    let minX = Infinity
    let maxY = -Infinity
    graph.getNodes().forEach((graphNode) => {
        if (downstreamNodeIdList.indexOf(graphNode.id) > -1) {
            const nodePosition = graphNode.getPosition()
            // 找到所有节点中最左侧的节点的x坐标
            if (nodePosition.x < minX) {
                minX = nodePosition.x
            }
            // 找到所有节点中最x下方的节点的y坐标
            if (nodePosition.y > maxY) {
                maxY = nodePosition.y
            }
        }
    })

    return {
        x: minX !== Infinity ? minX : position.x + dx,
        y: maxY !== -Infinity ? maxY + dy : position.y,
    }
}


// 根据节点的类型获取ports
export const getPortsByType = (type: NodeType, nodeId: string) => {
    let ports = []
    switch (type) {
        case NodeType.INPUT:
            ports = [
                {
                    id: `${nodeId}-out`,
                    group: 'out',
                },
            ]
            break
        case NodeType.OUTPUT:
            ports = [
                {
                    id: `${nodeId}-in`,
                    group: 'in',
                },
            ]
            break
        default:
            ports = [
                {
                    id: `${nodeId}-in`,
                    group: 'in',
                },
                {
                    id: `${nodeId}-out`,
                    group: 'out',
                },
            ]
            break
    }
    return ports
}

/**
 * 创建节点并添加到画布
 * @param type 节点类型
 * @param graph
 * @param position 节点位置
 * @returns
 */
export const createNode = (
    type: NodeType,
    graph: Graph,
    position?: Position,
) => {
    if (!graph) {
        return {}
    }
    let newNode = {}
    const sameTypeNodes = graph
        .getNodes()
        .filter((item) => item.getData()?.type === type)
    const typeName = PROCESSING_TYPE_LIST?.find(
        (item) => item.type === type,
    )?.name
    const id = StringExt.uuid()
    const node = {
        id,
        shape: 'data-processing-dag-node',
        x: position?.x,
        y: position?.y,
        ports: getPortsByType(type, id),
        data: {
            name: `${typeName}_${sameTypeNodes.length + 1}`,
            type,
        },
    }
    newNode = graph.addNode(node)
    return newNode
}

/**
 * 创建边并添加到画布
 * @param source
 * @param target
 * @param graph
 */
export const createEdge = (source: string, target: string, graph: Graph) => {
    const edge = {
        id: StringExt.uuid(),
        shape: 'data-processing-curve',
        source: {
            cell: source,
            port: `${source}-out`,
        },
        target: {
            cell: target,
            port: `${target}-in`,
        },
        zIndex: -1,
        data: {
            source,
            target,
        },
    }
    if (graph) {
        graph.addEdge(edge)
    }
}